
package com.borqs.music.http;

import static com.borqs.music.http.RequestMethod.POST;

import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import com.borqs.music.util.HttpRequestUtils;
import com.borqs.music.util.MD5Utils;
import com.borqs.music.util.MyLogger;

/**
 * HTTP Request parameter object
 */
public final class HttpRequest {
    private static final MyLogger logger = MyLogger.getLogger(HttpRequest.class.getSimpleName());

    private final RequestMethod method;

    private final String url;

    private final Map<String, String> parameters;
    private final Map<String, File> fileMap;

    private Map<String, String> requestHeaders;
    private RequestListener mListener;

    /**
     *
     * @param method
     * @param url
     * @param ticket
     * @param params
     * @param fileMap
     */
    public HttpRequest(RequestMethod method, String url, String ticket,
            Map<String, String> params,
            Map<String, File> fileMap) {

        this.fileMap = fileMap;
        this.parameters = new HashMap<String, String>();

        if (null == params) {
            params = new HashMap<String, String>();
        }

        // Generate Signature
        parameters.put("sign", generateSignature(params, fileMap));

        // put fixed parameters, which not include in Signature
        if (ticket != null && ticket.length() > 0) {
            parameters.put("ticket", ticket);
        }
        parameters.put("appid", HttpConfiguration.APP_ID);
        parameters.put("sign_method", "md5");

        parameters.putAll(params);

        this.method = method;

        if (method != POST) {
            this.url = url + "?" + HttpRequestUtils.encodeParameters(parameters);
        } else {
            this.url = url;
        }

        logger.d("Request url is :" + url);
    }

    public HttpRequest(RequestMethod method, String url, String ticket,
            Map<String, String> params) {
        this(method, url, ticket, params, null);
    }

    public RequestMethod getMethod() {
        return method;
    }

    public Map<String, String> getParameters() {
        return parameters;
    }

    public Map<String, String> getRequestHeaders() {
        return requestHeaders;
    }

    public void setRequestHeaders(Map<String, String> headers) {
        requestHeaders = headers;
    }

    public Map<String, File> getFileMap() {
        return fileMap;
    }

    public String getURL() {
        return url;
    }

    public RequestListener getListener() {
        return mListener;
    }

    public void registerListener(RequestListener listener) {
        mListener = listener;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }

        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        HttpRequest that = (HttpRequest) o;
        if (method != null ? !method.equals(that.method) : that.method != null) {
            return false;
        }

        if (url != null ? !url.equals(that.url) : that.url != null) {
            return false;
        }

        if (fileMap != null ? !fileMap.equals(that.fileMap)
                : that.fileMap != null) {
            return false;
        }

        if (parameters != null ? !parameters.equals(that.parameters)
                : that.parameters != null) {
            return false;
        }
        if (requestHeaders != null ? !requestHeaders.equals(that.requestHeaders)
                : that.requestHeaders != null) {
            return false;
        }

        return true;
    }

    @Override
    public int hashCode() {
        int result = method != null ? method.hashCode() : 0;
        result = 31 * result + (url != null ? url.hashCode() : 0);
        result = 31 * result + (fileMap != null ? fileMap.hashCode() : 0);
        result = 31 * result + (parameters != null ? parameters.hashCode() : 0);
        result = 31 * result + (requestHeaders != null ? requestHeaders.hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        return "HttpRequest{" +
                "requestMethod=" + method +
                ", url='" + url + '\'' +
                ", fileMap =" + fileMap +
                ", parameters =" + parameters +
                ", requestHeaders=" + requestHeaders +
                '}';
    }

    private static String generateSignature(Map<String, String> params, Map<String, File> fileMap) {
        Set<String> allKeySet = new HashSet<String>();
        allKeySet.addAll(params.keySet());
        if (null != fileMap) {
            allKeySet.addAll(fileMap.keySet());
        }

        TreeSet<String> sortedParamNames = new TreeSet<String>(allKeySet);
        StringBuilder sb = new StringBuilder();
        sb.append(HttpConfiguration.APP_SECRECT);
        for (String param : sortedParamNames) {
            sb.append(param);
        }
        sb.append(HttpConfiguration.APP_SECRECT);
        String str = MD5Utils.md5Base64(sb.toString().getBytes());
        return str;
    }
}
